package de.altitude.cimuelle.simulator;


import de.altitude.cimuelle.Config;
import de.altitude.cimuelle.LogParser;
import org.apache.log4j.PropertyConfigurator;

import javax.naming.ConfigurationException;
import java.io.*;
import java.net.URL;

/**
 * User: cybernaut
 * Date: 28.09.11
 * Time: 18:43
 */
public class AltitudeServerSimulator {
    Config config;
    private static org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("AltitudeServerSimulator");
    private boolean running = true;
    private Thread t;
    private boolean doSimulate;

    public AltitudeServerSimulator(String arg) {
        config = Config.getInstance(arg);
        simulateServer();
    }

    public AltitudeServerSimulator(String arg, String arg1) {

        config = Config.getInstance(arg, arg1);
        simulateServer();
    }

    private void simulateServer() {
        final String filename = config.getConfig("simulateFile", "");
        final String serverLogFile = config.getConfig("logfile", "");
        if (!"".equals(filename) && !new File(filename).isFile() && !"".equals(serverLogFile) && !new File(serverLogFile).exists()) {
            return;
        }

        Runtime.getRuntime().addShutdownHook(
                new Thread() {
                    @Override
                    public void run() {
                        log.info("Set running to false.");
                        running = false;
                        t.interrupt();
                    }
                });

        t = new Thread() {
            @Override
            public void run() {

                log.info("Cleaning Files...");
                File pseudoLog = new File(filename);
                File logFile = new File(serverLogFile);
                deleteAndCreate(logFile);
                File commandFile = new File(config.getCommandFile());
                deleteAndCreate(commandFile);

                log.info("Starting Simulation Thread...");
                while (!doSimulate) {
                    log.info("Simulation on hold, waiting for go...");
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        log.error(e);
                        e.printStackTrace();
                        if (!running) return;
                    }
                }
                RandomAccessFile ra = null;
                BufferedWriter bw = null;

                try {
                    ra = new RandomAccessFile(pseudoLog, "r");
                    bw = new BufferedWriter(new FileWriter(logFile, true));

                    while (running) {
                        String line = ra.readLine();
                        if (line == null) {
                            running = false;
                        } else {
                            log.info(new StringBuilder().append("Sending line: '").append(line).append("'").toString());
                            bw.write(line);
                            bw.newLine();
                            bw.flush();

                            sleep((long) (Math.random() * 100));
                        }
                    }
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (ra != null) {
                        try {
                            ra.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (bw != null) {
                        try {
                            bw.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    log.info("Shuting down Thread");
                    try {
                        Thread.sleep(3000);
                        //LogParser.externalStop();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        t.start();
    }

    private void deleteAndCreate(File logFile) {
        if (logFile.delete()) {
            try {
                logFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public static void main(String[] args) throws ConfigurationException, InterruptedException {
        String log4jName = "log4j.properties";
        File log4j = new File(log4jName);
        if (log4j.exists()) {
            PropertyConfigurator.configureAndWatch(log4j.getAbsolutePath());
            log.info("Logger configuration from " + log4jName + " loaded.");
        } else {
            Class resourceClass = LogParser.class;
            URL url = resourceClass.getResource("/log4j_internal.properties");
            PropertyConfigurator.configure(url);
            log.info("Logger configuration from internal resources used.");
        }

        log.info("Starting...");

        AltitudeServerSimulator simulator;
        if (args.length == 1) {
            simulator = new AltitudeServerSimulator(args[0]);
            LogParser.main(args);
            Thread.sleep(1000);
            simulator.doSimulate = true;
        } else if (args.length == 2) {
            simulator = new AltitudeServerSimulator(args[0], args[1]);
            LogParser.main(args);
            Thread.sleep(1000);
            simulator.doSimulate = true;
        } else {
            System.out.println("" +
                    "Usage: java -jar file.jar \n" +
                    "   [path to configfile]\n" +
                    "   [path to userconfigfile]\n" +
                    "\n" +
                    "       configfile:\n" +
                    "           port.active=(true|false) : active for server with port x as number" +
                    "           [port.]welcomeMessage : send entry message\n" +
                    "           commandfile : command.txt from server\n" +
                    "           [filename] : log.txt file from server\n" +
                    "           [updatetime] : sec between updates\n" +
                    "           [sleepTime] : sleep between updates\n" +
                    "           [configReloadTime] : sleep between config update check\n" +
                    "           [debug=(true|false)] : Debug output" +
                    "");
        }
    }
}
